/*
 * SearchCollectionAction.java
 * Copyright (c) 2006, FMap
 *
 * Created on 10 de febrero de 2006, 19:52
 */

package fmap.actions.collection.searchCollection;

import fmap.actions.mapF.searchMapF.SearchMapFTh;
import fmap.actions.mapF.searchMapF.SearchMapFEvt;
import fmap.DatosCompartidos;
import fmap.actions.EvtThread;
import fmap.dao.NodeDao;
import fmap.gui.jTreePersonal.TreeModelPersonal;
import fmap.model.MapF;
import java.util.Collections;
import java.util.Vector;

/**
 * Accion para buscar una cadena de texto en los mapas de ficheros de una coleccion
 * Desde esta clase se lanzara un hilo por cada mapa de ficheros a buscar
 *
 * @author  Javier Sanroman Araujo
 * @version $Revision: 1.1
 */
public class SearchCollectionAction implements SearchMapFEvt
{
    // Vector con los objetos MapF sobre los que realizar la busqueda
    Vector vMapF = new Vector ();

    // Numeros de hilos que van a estar buscando simultaneamente
    int numHilos = 3;
    
    // Buffer de hilos
    Thread[] bfTh;
    
    // Nos indica cual es el siguiente hilo que debemos lanzar, si es -1 es que ya no existen hilos por lanzar
    int hSiguiente = 0;
    // Nos indica el numero de hilos que todavia quedan por finalizar
    int hRestantes = 0;
    // Cadena de texto a buscar
    String txtSearch;
    
    boolean checkBoxCase;


    public SearchCollectionAction ( boolean _checkBoxCase )
    {
        checkBoxCase = _checkBoxCase;

        DatosCompartidos.getCollectionActual ().setName ( DatosCompartidos.getCollectionActual ().getName2 ()+" [ buscando... ]" );
        DatosCompartidos.getJTreePersonal ().repaint ();

        txtSearch  = DatosCompartidos.getJFrameMain ().getTxtBuscador ().getText ();
        vMapF      = DatosCompartidos.getCollectionActual ().getVMapF ();

        // Eliminamos todos los resultados de las busquedas anteriores de la BD
        new NodeDao ().deleteNodeResultSearch ();

        comenzarBusqueda ();
    }


    /**
     * Carga el buffer con los hilos de la busqueda, 1 por cada mapa de ficheros
     */
    private void cargarBuffer ()
    {
        // Si tenemos mapas de ficheros en los que buscar
        if( vMapF.size ()>0 )
        {
            
            hRestantes = vMapF.size ();
            bfTh = new Thread[vMapF.size ()];
            
            for( int i=0; i<vMapF.size (); i++ )
            {
                
                MapF mapF = (MapF)vMapF.get (i);
                mapF.setName ( mapF.getName2 () );
                mapF.setNumResult (0);
                mapF.setEstado (1);

                // Construimos el hilo que mas tarde lanzaremos
                SearchMapFTh h = new SearchMapFTh ( mapF , txtSearch,  i, checkBoxCase);
                // Añadimos esta clase como listener para que reciba los eventos necesarios (finBusqueda).
                h.addMiEventoListener (this);
                // Lo almacenamos en nuestro array de hilos
                bfTh[i] = new Thread (h);

            }
            
        } // if
    }
    
    
    /**
     * Carga el buffer con los hilos a lanzar y
     * comienza la busqueda en los mapas de ficheros lanzando los primeros hilos
     */
    public void comenzarBusqueda ()
    {
        cargarBuffer ();
        
        // Si existen hilos para lanzar
        if(bfTh.length>0)
        {
            
            if( numHilos > bfTh.length )    numHilos = bfTh.length;
            
            for(int i=0; i<numHilos; i++)
            {
                bfTh[i].start ();

                hSiguiente++;
                
                MapF mapF = (MapF)vMapF.get (i);
                mapF.setName ( mapF.getName2 ()+" [ buscando... ]");
            }
        }

        DatosCompartidos.getJTreePersonal ().repaint ();    
    }

    /**
     * Evento al que notificará el hilo el fin de la busqueda, en este momento el hilo termina
     */
    public synchronized void finBusqueda ( EvtThread e )
    {
        // Obtenemos el hilo que ha generado el evento
        SearchMapFTh th = (SearchMapFTh)e.getSource ();
        
        // Obtenemos el resultado de la busqueda
        MapF mapFSResult = th.getMapFResult ();

        mapFSResult.setName ( mapFSResult.getName2 ()+" ["+mapFSResult.getNumResult ()+" resultados encontrados]");


        // Insertamos en el vector de mapas de ficheros que constituye el modelo del JTree del buscador
        // el mapa de ficheros resultante de la busqueda, este no incluye los directorios y ficheros ya que estos
        // se almacenan en el fichero xml
        vMapF.set (th.getID (), mapFSResult);

//        DatosCompartidos.getJTreePersonal ().repaint ();    

        // Eliminamos el hilo que termina del array de hilos
        bfTh[th.getID ()] = null;
        
        hRestantes--; // Ya queda uno menos por lanzar
        
        if( hSiguiente != -1 )
        {
            // Comprobamos si existen mas hilos por lanzar
            if( hSiguiente >= bfTh.length )
            {
                hSiguiente = -1;
            }
            else
            {
                bfTh[hSiguiente].start ();
                
                hSiguiente++;
            }
        } //if
        
                
        // Si ya no quedan mas hilos por lanzar asignamos el numero de mapas de ficheros encontrados al titulo
        // de la coleccion
        // y ordenamos los mapas de ficheros por el numero de resultados
        if( hRestantes == 0 )
        {
            DatosCompartidos.ordenMapF = 3;
            DatosCompartidos.getCollectionActual ().setName ( DatosCompartidos.getCollectionActual ().getName2 () );
            Collections.sort ( vMapF );

            DatosCompartidos.getJFrameMain ().getRadioButtonArbol ().setSelected ( true );
            DatosCompartidos.getJFrameMain ().getPestana ().setSelectedIndex (1);
        }
        
        // Actualizamos la coleccion con el resultado de la busqueda de este mapa de ficheros
        DatosCompartidos.getCollectionActual ().setVMapF ( vMapF );

        // Creamos y enviamos un nuevo modelo al JTree del buscador
        TreeModelPersonal tmpB = new TreeModelPersonal ( DatosCompartidos.getCollectionActual () );
        DatosCompartidos.getJTreePersonal ().setModel ( tmpB );

//        DatosCompartidos.getJTreeP ().repaint ();
    } // public synchronized void finBusqueda
    
}